package com.york.tinyrpc.protoss.server.tcp;

import com.york.tinyrpc.protoss.enums.TinyRpcProtocolMessageTypeEnum;
import com.york.tinyrpc.protoss.model.TinyRpcRequest;
import com.york.tinyrpc.protoss.model.TinyRpcResponse;
import com.york.tinyrpc.protoss.protocol.TinyRpcProtocolMessage;
import com.york.tinyrpc.protoss.server.BaseServerHandler;
import com.york.tinyrpc.protoss.server.tcp.wrapper.TcpBufferHandlerWrapper;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * protoss版本：基于自拟协议的请求处理器(底层是靠TCP只是自拟了请求头以及编码解码方式)
 * provider是提供方，提供方在RPC中扮演了Server的角色
 * 请求处理器，执行流程如下
 * 1. 反序列化【请求】为对象，并从请求对象中获取参数
 * 2. 根据服务名称从【本地注册器】中获取到对应的【服务实现类】
 * 3. 通过反射机制调用方法，得到返回结果
 * 4. 对返回结果进行封装和序列化，并写入到【响应】中
 */
public class VertxTcpServerHandler
        extends BaseServerHandler
        implements Handler<NetSocket> {

    private static final Logger log = LoggerFactory.getLogger(VertxTcpServerHandler.class);


    /**
     * 请求处理方法
     *
     * @param netSocket
     */
    @Override
    public void handle(NetSocket netSocket) {
        // 使用引入了RecordParser的增强版Handle<Buffer>
        TcpBufferHandlerWrapper handlerWrapper = new TcpBufferHandlerWrapper(buffer -> {
            // 使用规定的解码方式获取请求体
            TinyRpcProtocolMessage<TinyRpcRequest> message;
            try {
                message = (TinyRpcProtocolMessage<TinyRpcRequest>) TinyRpcProtocolMessage.decode(buffer);
            } catch (IOException e) {
                throw new RuntimeException("协议消息解码错误");
            } catch (ClassCastException e) {
                throw new RuntimeException("类型转换错误");
            }
            TinyRpcRequest rpcRequest = message.getBody();

            // 处理请求，构造响应结果
            TinyRpcResponse rpcResponse = new TinyRpcResponse();
            try {
                rpcResponse = VertxTcpServerHandler.getResponseByRequest(rpcRequest);
                log.info("TinyRPC 调用成功, rpcRequest:{}, rpcResponse:{}", rpcRequest, rpcResponse);
            } catch (Throwable e) {
                log.error("TinyRPC 调用失败, rpcRequest:{}, rpcResponse:{}", rpcRequest, rpcResponse);
            }

            // 封装响应请求并编码发送
            TinyRpcProtocolMessage.TinyRpcProtocolMessageHeader header = message.getHeader();
            header.setType((byte) TinyRpcProtocolMessageTypeEnum.RESPONSE.getType());
            // 使用Lombok注解@Builder带有泛型时，直接传入对象返回的是Object类型，在builder前使用泛型规定即可
            TinyRpcProtocolMessage<TinyRpcResponse> responseProtocolMessage = TinyRpcProtocolMessage.<TinyRpcResponse>builder()
                    .header(header)
                    .body(rpcResponse)
                    .build();
            Buffer encode = TinyRpcProtocolMessage.encode(responseProtocolMessage);
            netSocket.write(encode);
        });

        // netSocket处理请求
        netSocket.handler(handlerWrapper);
    }
}
